package com.cssl.service.impl;

import cn.dev33.satoken.exception.NotLoginException;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cssl.domain.*;
import com.cssl.domain.dto.DtsBrandDto;
import com.cssl.domain.dto.GoodsDto;
import com.cssl.domain.dto.GoodsSearchDto;
import com.cssl.domain.dto.PageDto;
import com.cssl.mapper.DtsGoodsMapper;
import com.cssl.mapper.DtsUserMapper;
import com.cssl.mapper.GroupOnMapper;
import com.cssl.service.DtsFootprintService;
import com.cssl.service.DtsGoodsService;
import com.cssl.util.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class DtsGoodsServiceImpl implements DtsGoodsService {
    @Autowired
    private ThreadPool threadPool;
    @Autowired
    private DtsFootprintService service;
    private ExecutorService pool;
    @Autowired
    private DtsGoodsMapper mapper;
    @Autowired
    private GroupOnMapper groupOnMapper;
    @Autowired
    private StringRedisTemplate template;
    @Resource
    private DtsUserMapper userMapper;
    @Autowired
    private ObjectMapperUtil objectMapperUtil;
    /**
     * 用来存储第一次模糊查询商品后的二级id
     */
    private List<Map> categoryIdCache;
    /**
     * 用来判断传的key是否一致
     */
    private String keyWord;

    @PostConstruct
    private void init() {
        pool = threadPool.getPool();
    }

    /**
     * 首页商品展示
     *
     * @return
     */
    @Override
    public Page findFirstPageGoods(com.cssl.domain.Page pages) {
        Page page = PageHelper.startPage(pages.getPageIndex(), pages.getPageSize());
        mapper.findFirstPageGoods();
        return page;
    }

    @Override
    public List<DtsGoods> getTwoHotGoods() {
        return mapper.getTwoHotGoods();
    }

    /**
     * 商品列表
     *
     * @param goodsDto 查询条件
     * @return
     */
    @Override
    public Map getGoodsList(GoodsDto goodsDto) {
        Page page = PageHelper.startPage(goodsDto.getPageNum(), goodsDto.getPageSize());
        mapper.getGoodsList(goodsDto);
        Map map = new HashMap();
        map.put("list", page.getResult());
        map.put("total", page.getTotal());
        map.put("totalPage", page.getPages());
        map.put("pageNum", page.getPageNum());
        map.put("pageSize", page.getPageSize());
        return map;
    }

    @Override
    public Result getTotalGoodsCount() {
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, mapper.getTotalGoodsCount(), System.currentTimeMillis());
    }

    @Override
    public List<DtsGoods> getNewGoods() {
        return mapper.getNewGoods();
    }

    @Override
    public List<DtsGoods> getHotGoods() {
        return mapper.getHotGoods();
    }

    @Override
    public List<DtsAd> findNoticeList() {
        return mapper.findNoticeList();
    }

    @Override
    public Result getNotice(Integer id) {
        //先从redis获取(String存储 键:notice:id) 0 查全部
        String s = template.opsForValue().get(StorageVariable.NOTICE + ":" + id);
        if (StrUtil.isEmpty(s)) {
            //查询数据库
            List<DtsArticle> notice = mapper.getNotice(id);
            template.opsForValue().set(StorageVariable.NOTICE + ":" + id, objectMapperUtil.toJsonString(notice), 7, TimeUnit.DAYS);
            return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, notice, System.currentTimeMillis());
        }
        //不为空
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, objectMapperUtil.fromJsonString(s, new TypeReference<List<DtsArticle>>() {
        }), System.currentTimeMillis());
    }

    /**
     * 狗屎代码,后期是否能优化
     *
     * @param parseInt
     * @return
     */
    @Override
    public Result getGoodsInfoById(int parseInt) {
        //先从redis中获取属性
        List<Future<Map<String, Object>>> futures = new ArrayList<>();
        List<String> redisKeys = Arrays.asList(
                StorageVariable.GOODSBASEINFO + ":" + parseInt,//基础信息
                StorageVariable.GOODSCOMMENT + ":" + parseInt,//评价
                StorageVariable.BRAND + ":" + parseInt,//品牌
                StorageVariable.GOODSATTRIBUTE + ":" + parseInt, //属性
                StorageVariable.GOODSCOMMENT + ":" + parseInt, //商品评论
                StorageVariable.GOODSPROBLEM + ":" + parseInt //问题
                // 添加其他 Redis 查询键
        );

        String regex = "[^\\d]+";
        Pattern pattern = Pattern.compile(regex);
        for (String key : redisKeys) {
            Matcher matcher = pattern.matcher(key);
            StringBuilder resultKey = new StringBuilder();
            while (matcher.find()) {
                resultKey.append(matcher.group());
            }
            String[] splitKey = resultKey.toString().split(":");
            futures.add(pool.submit(() -> {
                Map<String, Object> result = new HashMap<>();
                Object value = template.opsForValue().get(key);
                if (value != null) {
                    result.put(splitKey[1], value);
                }
                return result;
            }));
        }


        Map<String, Object> redisData = new HashMap<>();


        List<String> missingKeys = new ArrayList<>();
        for (String key : redisKeys) {
            Matcher matcher = pattern.matcher(key);
            StringBuilder result = new StringBuilder();
            while (matcher.find()) {
                result.append(matcher.group());
            }
            String[] splitKey = result.toString().split(":");
            boolean found = false;
            for (Future<Map<String, Object>> future : futures) {
                try {
                    Map<String, Object> data = future.get();
                    if (data.containsKey(splitKey[1])) {
                        redisData.put(splitKey[1].toString(), objectMapperUtil.fromJsonString(data.get(splitKey[1]).toString(), new TypeReference<Object>() {
                        }));
                        found = true;
                        break;
                    }
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace(); // 处理异常
                }
            }
            if (!found) {
                missingKeys.add(key);
            }
        }

        //最终结果查询
        Map<String, Object> map = redisData;
        // 仅对缺失的数据进行数据库查询
        missingKeys.stream().forEach(s -> {
            //redis商品基础信息为空
            if ((StorageVariable.GOODSBASEINFO + ":" + parseInt).equals(s)) {
                DtsGoods goodsById = mapper.getGoodsById(parseInt);
                String[] parts = StorageVariable.GOODSBASEINFO.split(":");
                map.put(parts[1], goodsById);
                template.opsForValue().set(StorageVariable.GOODSBASEINFO + ":" + parseInt, objectMapperUtil.toJsonString(goodsById), 7, TimeUnit.DAYS);
            }
            //商品评分为空
            if ((StorageVariable.GOODSCOMMENT + ":" + parseInt).equals(s)) {
                String[] parts = StorageVariable.GOODSCOMMENT.split(":");
                List<DtsComment> commentList = mapper.getGoodsCommentById(parseInt);
                map.put(parts[1], commentList);
                template.opsForValue().set(StorageVariable.GOODSCOMMENT + ":" + parseInt, objectMapperUtil.toJsonString(commentList), 7, TimeUnit.DAYS);
            }
            //品牌为空
            if ((StorageVariable.BRAND + ":" + parseInt).equals(s)) {
                String[] parts = StorageVariable.BRAND.split(":");
                List<Map> brandMap = mapper.getGoodsBrandById(parseInt);
                map.put(parts[1], brandMap);
                template.opsForValue().set(StorageVariable.BRAND + ":" + parseInt, objectMapperUtil.toJsonString(brandMap), 7, TimeUnit.DAYS);
            }
            //商品属性为空
            if ((StorageVariable.GOODSATTRIBUTE + ":" + parseInt).equals(s)) {
                String[] parts = StorageVariable.GOODSATTRIBUTE.split(":");
                List<DtsGoodsAttribute> specifications = mapper.getGoodsAttribute(parseInt);
                map.put(parts[1], specifications);
                template.opsForValue().set(StorageVariable.GOODSATTRIBUTE + ":" + parseInt, objectMapperUtil.toJsonString(specifications), 7, TimeUnit.DAYS);
            }
            //商品评论为空
            if ((StorageVariable.GOODSCOMMENT + ":" + parseInt).equals(s)) {
                String[] parts = StorageVariable.GOODSCOMMENT.split(":");
                List<DtsComment> goodsCommentById = mapper.getGoodsCommentById(parseInt);
                map.put(parts[1], goodsCommentById);
                template.opsForValue().set(StorageVariable.GOODSCOMMENT + ":" + parseInt, objectMapperUtil.toJsonString(goodsCommentById), 7, TimeUnit.DAYS);
            }
            //商品问题为空
            if ((StorageVariable.GOODSPROBLEM + ":" + parseInt).equals(s)) {
                String[] parts = StorageVariable.GOODSPROBLEM.split(":");
                List<DtsIssue> issueList = mapper.getAllIssueList(0);
                map.put(parts[1], issueList);
                template.opsForValue().set(StorageVariable.GOODSPROBLEM + ":" + parseInt, objectMapperUtil.toJsonString(issueList), 7, TimeUnit.DAYS);
            }
        });
        //团购优惠的金额
        List<DtsGroupOnRules> discount = mapper.getGoodsDiscount(parseInt);
        Integer loginIdAsInt = 0;
        //用户是否收藏该商品
        try {
            loginIdAsInt = StpKit.USER.getLoginIdAsInt();
        } catch (NotLoginException e) {
            System.out.println(e);
        }
        if (loginIdAsInt != null) {
            final Integer userId = loginIdAsInt;
            //异步执行添加用户浏览足迹(已做是否存在的判断)
            pool.execute(() -> service.addFootPrint(userId, parseInt));
        }


        //返回默认选中的json
        DtsGoodsProduct combination = mapper.getCombination(Integer.parseInt(parseInt + ""));//获得第一个json数组
        Integer flag = userMapper.userHasGoodsCollect(loginIdAsInt, parseInt);
        //前端要求:单独将gallery写出来
        List<String> imageList;
        Object baseInfo = map.get("baseInfo");
        DtsGoods dtsGoods = transToList(baseInfo);
        imageList = objectMapperUtil.fromJsonString(dtsGoods.getGallery(), new TypeReference<List<String>>() {
        });


        map.put("imageList", imageList);
        map.put("flag", flag);
        map.put("baseInfo", dtsGoods);
        map.put("groupon", discount);
        map.put("combination", combination);
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, map, System.currentTimeMillis());
    }


    private DtsGoods transToList(Object obj) {
        String jsonStr = JSON.toJSONString(obj);//依旧使用alibaba提供的json转换工具。
        return JSONObject.parseObject(jsonStr, DtsGoods.class);
    }

    @Override
    public Result searchHelp() {
        //使用redis获得商品关键词
        String s = template.opsForValue().get(StorageVariable.GOODSKEY);
        List<String> goodsKey;
        if (StrUtil.isEmpty(s)) {
            //
            goodsKey = mapper.allGoodsKey();
            template.opsForValue().set(StorageVariable.GOODSKEY, objectMapperUtil.toJsonString(goodsKey), 7, TimeUnit.DAYS);
        } else {
            goodsKey = objectMapperUtil.fromJsonString(s, new TypeReference<List<String>>() {
            });
        }
        Integer loginIdAsInt = null;
        try {
            loginIdAsInt = StpKit.USER.getLoginIdAsInt();
        } catch (NotLoginException e) {
            System.out.println(e);
        }

        Set<String> strings = GoodsRandomKey.poolResult(goodsKey);
        List<String> collect = strings.stream().collect(Collectors.toList());
        Collections.shuffle(collect, new Random());
        // 选择前十条数据
        List<String> randomItems = collect.subList(0, 10);
        List<DtsHotKey> hotKeys = mapper.hotKey();
        List<DtsSearchHistory> historyList = null;
        if (loginIdAsInt != null) {
            historyList = mapper.historyKey(loginIdAsInt);
        }
        Map map = new HashMap();
        map.put("hotKeyWordList", hotKeys);
        map.put("goodsKeyWordList", randomItems);
        //只返回历史记录的前十条
        map.put("historyList", historyList);
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, map, System.currentTimeMillis());
    }

    @Override
    public Result searchGoods(GoodsSearchDto searchDto) {
        try {
            Integer loginIdAsInt = StpKit.USER.getLoginIdAsInt();
            if (loginIdAsInt != null) {
                //先判断是否为空
                Integer exist = SaveUserSearch.isExist(searchDto.getKeyword(), loginIdAsInt, userMapper);
                if (exist <= 0) {
                    //不存在
                    SaveUserSearch.save(searchDto.getKeyword(), loginIdAsInt, userMapper);
                }
            }
        } catch (NotLoginException e) {
            System.out.println("e = " + e);
        }
        Integer page1 = searchDto.getPage();
        Integer size = searchDto.getSize();
        Page page = PageHelper.startPage(page1, size);
        mapper.searchGoods(searchDto);
        Map map = new HashMap();
        map.put("goodsList", page.getResult());
        map.put("page", page.getPages());


        //说明两次查询的关键词均一致
        if (searchDto.getKeyword().equals(keyWord)) {
            map.put("categoryName", categoryIdCache);
        } else {
            //不一致(或第一次为空)
            keyWord = searchDto.getKeyword();
            List<Integer> collect = mapper.searchCategoryId(searchDto).stream().distinct().collect(Collectors.toList());
            categoryIdCache = mapper.getCategoryName(collect);
            map.put("categoryName", categoryIdCache);
        }
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, map, System.currentTimeMillis());
    }

    @Override
    public Integer deleteHistory(Integer loginIdAsInt) {
        return userMapper.deleteHistory(loginIdAsInt);
    }

    @Override
    public Result getGoodsSpecifications(Map map) {
        Object goodsId = map.get("goodsId");
        if (ObjectUtil.isEmpty(goodsId)) {
            return Result.fail(InfoCode.BAD_REQUEST, InfoCode.MESSAGE_BAD_REQUEST, System.currentTimeMillis());
        }
        //商品的全部规格信息
        List<DtsGoodsSpecification> goodsSpecifications = mapper.getGoodsSpecifications(Integer.parseInt(goodsId.toString()));
        Map<String, List<String>> result = goodsSpecifications.stream()
                .collect(Collectors.groupingBy(
                        DtsGoodsSpecification::getSpecification,
                        Collectors.mapping(DtsGoodsSpecification::getValue, Collectors.toList())
                ));

        DtsGoodsProduct combination = mapper.getCombination(Integer.parseInt(goodsId.toString()));//获得第一个json数组
        String[] strings;
        strings = objectMapperUtil.fromJsonString(combination.getSpecifications(), String[].class);
        Map maps = new HashMap();
        maps.put("checked", strings);
        maps.put("result", result);
        maps.put("goodsImageUrl", combination);
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, maps, System.currentTimeMillis());
    }

    @Override
    public Result getRelevantData(Map map) {
        Integer goodsId = Integer.parseInt(map.get("id").toString());
        String specifications = map.get("specifications").toString(); //选中的规格
        specifications = specifications.substring(1, specifications.length() - 2); /**=> 颜色','规格','信息 */
        String[] split = specifications.split("','");
        List<String> strings = Arrays.asList(split);
        List<DtsGoodsProduct> products = mapper.getRelevantData(goodsId, strings);
        if (ObjectUtil.isEmpty(products)) {
            return Result.fail(InfoCode.QUERY_EMPTY, InfoCode.MESSAGE_QUERY_EMPTY, System.currentTimeMillis());
        }
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, products, System.currentTimeMillis());
    }

    @Override
    public Result getGoodsByBrandId(DtsBrandDto dto) {
        Page page = PageHelper.startPage(dto.getPage(), dto.getSize());
        mapper.getGoodsByBrandId(dto.getBrandId());
        Map map = new HashMap();
        map.put("goodsList", page.getResult());
        map.put("totalPages", page.getPages());
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, map, System.currentTimeMillis());
    }


    @Override
    public Result getHotAndNewGoods(PageDto dto) {
        Page page = PageHelper.startPage(dto.getPage(), dto.getSize());
        mapper.getPageHotOrNewGoods(dto);
        Map map = new HashMap();
        map.put("goodsList", page.getResult());
        map.put("totalPages", page.getPages());
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, map, System.currentTimeMillis());
    }

    @Override
    public Result checkedSpecPrice(Map map) {
        Integer goodsId = Integer.parseInt(map.get("id").toString());
        String specifications = map.get("checkedSpecText").toString(); //选中的规格
        specifications = specifications.substring(1, specifications.length() - 2); /**=> 颜色','规格','信息 */
        String[] split = specifications.split("','");
        List<String> strings = Arrays.asList(split);
        List<Map> products = mapper.checkedSpecPrice(goodsId, strings);
        if (ObjectUtil.isEmpty(products)) {
            return Result.fail(InfoCode.QUERY_EMPTY, InfoCode.MESSAGE_QUERY_EMPTY, System.currentTimeMillis());
        }
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, products, System.currentTimeMillis());
    }

    @Override
    public Integer getGoodsLatSort() {
        return mapper.getGoodsLatSort();
    }

    @Override
    public Integer insertGoods(Map map) {
        pool.execute(() -> {
            Set<String> keys = template.keys("goods" + "*");
            System.out.println(keys.size());
            template.delete(keys);
        });
        Map goods = (Map) map.get("goods");
        DtsGoods dtsGoods = new DtsGoods();
// 使用 BeanUtil 将 Map 数据复制到 dtsGoods 对象
        BeanUtil.copyProperties(goods, dtsGoods);
// 手动设置剩余的属性
        dtsGoods.setGoodsSn("");
        dtsGoods.setSortOrder(this.getGoodsLatSort() + 1);
        dtsGoods.setAddTime(DateUtil.date());
        dtsGoods.setBrowse(0);
        dtsGoods.setSales(0);
        dtsGoods.setApproveStatus(0);
        Integer integer = mapper.insertGoods(dtsGoods);
        return integer;

    }

    @Override
    public Integer updateGoodsSn() {
        return mapper.updateGoodsSn();
    }

    @Override
    public Integer getNewGoodsSn() {
        return mapper.getNewGoodsSn();
    }

    @Override
    public Integer insertGoodsAttribute(Map map) {
        Integer flag = 0;
        List<Map<String, Object>> attributes = (List<Map<String, Object>>) map.get("attributes");
        for (Map<String, Object> map2 : attributes) {
            DtsGoodsAttribute dtsGoodsAttribute = new DtsGoodsAttribute();
            dtsGoodsAttribute.setGoodsId(Integer.valueOf(map.get("id").toString()));
            dtsGoodsAttribute.setAttribute(map2.get("attribute").toString());
            dtsGoodsAttribute.setValue(map2.get("value").toString());
            dtsGoodsAttribute.setAddTime(new Date());
            dtsGoodsAttribute.setUpdateTime(new Date());
            flag = mapper.insertGoodsAttribute(dtsGoodsAttribute);
        }
        return flag;
    }

    @Override
    public Integer insertGoodsSpecification(Map map) {
        Integer flag = 0;
        List<Map<String, Object>> specifications = (List<Map<String, Object>>) map.get("specifications");
        for (Map<String, Object> map2 : specifications) {
            DtsGoodsSpecification dtsGoodsSpecification = new DtsGoodsSpecification();
            dtsGoodsSpecification.setGoodsId(Integer.valueOf(map.get("id").toString()));
            dtsGoodsSpecification.setSpecification(map2.get("specification").toString());
            dtsGoodsSpecification.setValue(map2.get("value").toString());
            dtsGoodsSpecification.setPicUrl(map2.get("picUrl").toString());
            dtsGoodsSpecification.setAddTime(new Date());
            dtsGoodsSpecification.setUpdateTime(new Date());
            flag = mapper.insertGoodsSpecification(dtsGoodsSpecification);
        }

        return flag;
    }

    @Override
    public Integer insertGoodsProduct(Map map) {
        Integer flag = 0;
        List<Map<String, Object>> products = (List<Map<String, Object>>) map.get("products");
        for (Map<String, Object> map2 : products) {
            DtsGoodsProduct dtsGoodsProduct = new DtsGoodsProduct();
            dtsGoodsProduct.setGoodsId(Integer.valueOf(map.get("id").toString()));
            dtsGoodsProduct.setSpecifications(map2.get("specifications2").toString());
            dtsGoodsProduct.setPrice(Double.valueOf(map2.get("price").toString()));
            dtsGoodsProduct.setNumber(Integer.valueOf(map2.get("number").toString()));
            dtsGoodsProduct.setUrl(map2.get("url").toString());
            dtsGoodsProduct.setAddTime(new Date());
            dtsGoodsProduct.setUpdateTime(new Date());
            flag = mapper.insertGoodsProduct(dtsGoodsProduct);
        }
        return flag;
    }

    @Override
    public Result getGoodsRelated(DtsGoods goods) {
        Integer id = goods.getId();
        Integer categoryId = mapper.getCateGoryIdByGoodsId(id);
        List<DtsGoods> goods1 = mapper.getGoodsRelated(categoryId, id);
        return Result.result(InfoCode.OK, InfoCode.MESSAGE_OK, goods1, System.currentTimeMillis());
    }

    @Override
    public DtsGoods getDtsGoodsById(Integer goodsId) {
        return mapper.getDtsGoodsById(goodsId);
    }

    @Override
    public List<DtsGoodsAttribute> getGoodsAttributeByGoodsId(Integer goodsId) {
        return mapper.getGoodsAttributeByGoodsId(goodsId);
    }

    @Override
    public List<DtsGoodsSpecification> getGoodsSpecificationByGoodsId(Integer goodsId) {
        return mapper.getGoodsSpecificationByGoodsId(goodsId);
    }

    @Override
    public List<DtsGoodsProduct> getGoodsProductByGoodsId(Integer goodsId) {
        return mapper.getGoodsProductByGoodsId(goodsId);
    }

    @Override
    public Integer deleteGoodsAttributeByGoodsId(Integer goodsId) {
        return mapper.deleteGoodsAttributeByGoodsId(goodsId);
    }

    @Override
    public Integer deleteGoodsSpecificationByGoodsId(Integer goodsId) {
        return mapper.deleteGoodsSpecificationByGoodsId(goodsId);
    }

    @Override
    public Integer deleteGoodsProductByGoodsId(Integer goodsId) {
        return mapper.deleteGoodsProductByGoodsId(goodsId);
    }

    @Override
    public Integer updateGoods(DtsGoods goods) {
        return mapper.updateGoods(goods);
    }

    @Override
    public Integer deleteGoods(Integer goodsId) {
        return mapper.deleteGoods(goodsId);
    }

    @Override
    public Integer goodsInOrder(Integer goodsId) {
        return mapper.goodsInOrder(goodsId);
    }


    @Override
    public Result groupOnShow(Integer goods) {
        //商品前两条团购
        List<Map> group = groupOnMapper.getGroupOnGoodsLimit(goods);
        return Result.result(InfoCode.OK,InfoCode.MESSAGE_OK,group,System.currentTimeMillis());
    }
}
